package containers;


import java.awt.Graphics2D;
import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.List;
import objects.Mass;
import objects.Spring;

/**
 * Assemblies hold all the objects that are loaded from a data file.
 * Different assemblies hold objects from different files
 * or that were instantiated later.
 * @author rwb10 & sab60
 *
 */
public class Assembly {
    private List<Mass> myMasses;
    private List<Spring> mySprings;
    private Simulation mySimulation;

    /**
     * Constructor
     * @param sim       The simulation that the assembly resides in.
     */
    public Assembly (Simulation sim) {
        myMasses = new ArrayList<Mass>();
        mySprings = new ArrayList<Spring>();
        mySimulation = sim;
        sim.addAssembly(this);
    }

    /**
     * 
     * @param mass Mass to add
     */
    public void add (Mass mass) {
        myMasses.add(mass);
        mass.setAssembly(this);
    }

    /**
     * 
     * @param spring Spring to add.
     */
    public void add (Spring spring) {
        mySprings.add(spring);
    }

    /**
     * Paint all shapes on the canvas.
     * 
     * @param pen used to paint shape on the screen.
     */
    public void paint (Graphics2D pen) {
        for (Spring s : mySprings) {
            s.paint(pen);
        }
        for (Mass m : myMasses) {
            m.paint(pen);
        }
    }

    /**
     * Called by each step of timer, multiple times per second.
     * 
     * This should update the state of the animated shapes by just
     * a little so they appear to move over time.
     * 
     * @param dt change in time.
     */
    public void update (double dt) {
        updateMovers(dt);
    }

    void updateMovers (double dt) {
        for (Spring s : mySprings) {
            s.update(mySimulation, dt);
        }
        for (Mass m : myMasses) {
            m.update(mySimulation, dt);
        }
    }

    /**
     * 
     * @param id Gets the mass asked for.
     * @return
     */
    public Mass getMass (int id) {
        for (Mass m : myMasses) {
            if (m.match(id)) {
                return m;
            }
        }
        return null;
    }
    /**
     * Removes the mass with a certain ID
     * @param id        The mass ID of the mass to be removed.
     */
    public void removeMass (int id) {
        for (Mass m : myMasses) {
            if (m.match(id)) {
                myMasses.remove(m);
            }
        }
    }

    /**
     * Removes a mass from the assembly.
     * @param m Mass to be removed.
     */
    public void removeMass (Mass m) {
        myMasses.remove(m);
    }

    /**
     * Removes a spring containing a mass ID from the assembly.
     * @param id        The Mass ID being searched for to delete.
     */
    public void removeSpring (int id) {
        for (Spring s : mySprings) {
            if (s.containsMass(id)) {
                mySprings.remove(s);
            }
        }
    }

    /**
     * Removes a spring from the assembly.
     * @param s Spring to be removed.
     */
    public void removeSpring (Spring s) {
        mySprings.remove(s);
    }

    /**
     * Access method for the Masses contained.
     * @return  ArrayList of the masses.
     */
    public List<Mass> getMasses () {
        return myMasses;
    }

    /**
     * Access method for the simulation.
     * @return  The simulation.
     */
    public Simulation getSimulation () {
        return mySimulation;
    }

    /**
     * Finds the center of mass of the assembly.
     * @return The center of mass location of an assembly.
     */
    public Point2D getCenter () {
        double x = 0;
        double y = 0;
        for (Mass m : myMasses) {
            x += m.getCenter().getX();
            y += m.getCenter().getY();
        }
        x /= myMasses.size();
        y /= myMasses.size();
        return new Point2D.Double(x, y);
    }
}
